#include "GEnginePCH.h"
#include "Support.h"
#include "main.h"
#include "FPSCounter.h"
#include "Terrain.h"
#include "Model.h"
#include "Entity.h"
#include "Camera.h"
#include "Projection.h"
#include "ParticleEmitter.h"
#include "Shaders.h"
#include "D3DApp.h"
#include "SkinnedMesh.h"
#include "Effects.h"


class GEngine : public D3DApp
{
public:

	GEngine(HINSTANCE hInstance, std::string winCaption, D3DDEVTYPE devType, DWORD requestedVP);
	~GEngine();
	void oneTimeSystemInit();
	void InvalidateDeviceObjects();
	void RestoreDeviceObjects();
	void Render();
	void DisplaySomeText(char *c, int x, int y);
	void LoadEntities(char* file);
	void InvalidateModels();
	void DeleteModels();
	void DeleteGameObjects();
private:

	//Objects
	FPSCounter *FPSc;
	LPD3DXFONT myFont;
	Terrain *map;
	Camera *camera;
	Projection *projection;
	ParticleEmitter PartSys, PartSys2;

	Entity *entities[100];
	Destructible *destructibles[100];
	Warrior *warriors[100];
	
	int SelectedWarriorIndex;
	bool selectedWarrior;

	Model *models[100];
	int nModels, nEntities, nDestructibles, nWarriors;

	DWORD currentTime, lastTime, deltaTime;
	
	DirLight mLight;
	Mtrl     mWhiteMtrl;
	SkinnedMesh* skinnedMesh;
	IDirect3DTexture9* mTex;
	
};


int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE prevInstance,
				   PSTR cmdLine, int showCmd)
{

	GEngine app(hInstance, "GEngine", D3DDEVTYPE_HAL, D3DCREATE_HARDWARE_VERTEXPROCESSING);
	gd3dApp = &app;

	return gd3dApp->run();
}

GEngine::GEngine(HINSTANCE hInstance, std::string winCaption, D3DDEVTYPE devType, DWORD requestedVP)
: D3DApp(hInstance, winCaption, devType, requestedVP)
{
	oneTimeSystemInit();
}



//-----------------------------------------------------------------------------
// Name: oneTimeSystemInit()
// Desc: This function will only be called once during the application's 
//       initialization phase. Therefore, it can't contain any resources that 
//       need to be restored every time the Direct3D device is lost or the 
//       window is resized.
//-----------------------------------------------------------------------------
void GEngine::oneTimeSystemInit()
{
	initDirect3D();


	
    // Any resources or settings that need to be restored after losing the 
    // DirectD device should probably be grouped together into one function so 
    // they can be re-created or reset in one call.

    RestoreDeviceObjects();
	ShowCursor(false);
	FPSc = new FPSCounter();
	FPSc->Init();

	lastTime=currentTime=timeGetTime();
	


	// set particle system properties
	PartSys.SetSpawnDir1(D3DXVECTOR3(-5.0f, 15.0f, -0.4f));
	PartSys.SetSpawnDir2(D3DXVECTOR3( 5.0f, 20.0f,  0.4f));
	PartSys.SetPos(D3DXVECTOR3(0.0f, 15.0f, 50.0f));
	PartSys.SetColor1(D3DXCOLOR(0.9f, 0.9f, 0.1f, 1.0f));
	PartSys.SetColor2(D3DXCOLOR(0.1f, 0.1f, 0.9f, 1.0f));
	PartSys.SetMinLife(4.0f);
	PartSys.SetMaxLife(4.0f);


	PartSys2.SetSpawnDir1(D3DXVECTOR3(-5.0f, 5.0f, -5.0f));
	PartSys2.SetSpawnDir2(D3DXVECTOR3( 5.0f, 5.0f,  5.0f));
	PartSys2.SetPos(D3DXVECTOR3(0.6f, 10.0f, 40.0f));
	PartSys2.SetColor1(D3DXCOLOR(1.0f, 0.0f, 0.0f, 1.0f));
	PartSys2.SetColor2(D3DXCOLOR(1.0f, 1.0f, 0.0f, 0.0f));
	PartSys2.SetMinLife(0.2f);
	PartSys2.SetMaxLife(2.0f);
	// initialize it!


	mLight.dirW    = D3DXVECTOR3(1.0f, 1.0f, 2.0f);
	D3DXVec3Normalize(&mLight.dirW, &mLight.dirW);
	mLight.ambient = D3DXCOLOR(0.5f, 0.5f, 0.5f, 1.0f);
	mLight.diffuse = D3DXCOLOR(0.8f, 0.8f, 0.8f, 1.0f);
	mLight.spec    = D3DXCOLOR(0.8f, 0.8f, 0.8f, 1.0f);

	mWhiteMtrl.ambient = WHITE*0.9f;
	mWhiteMtrl.diffuse = WHITE*0.6f;
	mWhiteMtrl.spec    = WHITE*0.6f;
	mWhiteMtrl.specPower = 48.0f;

	selectedWarrior = false;
	SelectedWarriorIndex = 0;

	//d3ddev->SetRenderState(D3DRS_FILLMODE, D3DFILL_WIREFRAME);
	//d3ddev->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
}

//-----------------------------------------------------------------------------
// Name: restoreDeviceObjects()
// Desc: You are encouraged to develop applications with a single code path to 
//       respond to device loss. This code path is likely to be similar, if not 
//       identical, to the code path taken to initialize the device at startup.
//-----------------------------------------------------------------------------
void GEngine::RestoreDeviceObjects()
{
    //
    // Set some important state settings...
    //
	D3DXVECTOR3 cameraSource(0.0f,30.0f,-20.0f), cameraTarget(0.0f,0.0f,80.0f), upDir(0.0f,1.0f,0.0f);
// 	D3DXVECTOR3 cameraSource(30.0f,0.0f,-20.0f),
// 		cameraTarget(0.0f,0.0f,0.0f), 
// 		upDir(0.0f,1.0f,0.0f);

	camera = new Camera();
	camera->Init( cameraSource, cameraTarget, upDir);

	projection = new Projection();
	projection->Init( D3DXToRadian(45.0f), (float)(SCREEN_WIDTH)/(SCREEN_HEIGHT), 0.1f, 1000.0f );
	
	
	
    d3ddev->SetRenderState( D3DRS_ZENABLE, TRUE );
    d3ddev->SetRenderState( D3DRS_LIGHTING, TRUE );
    d3ddev->SetRenderState( D3DRS_SPECULARENABLE, TRUE );
	
	

    d3ddev->SetRenderState( D3DRS_AMBIENT, D3DCOLOR_COLORVALUE( 0.2f, 0.2f, 0.2f, 1.0f ) );

    d3ddev->SetSamplerState( 0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR );
    d3ddev->SetSamplerState( 0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR );


	Shaders::Init();
	Effects::Init();

	// Create a D3DX font object
	D3DXCreateFont( d3ddev, 20, 0, FW_BOLD, 0, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, TEXT("Arial"), &myFont );
	
	LoadEntities("../data/maps/map2.txt");

	map = new Terrain();
	D3DXMATRIX mat;//doesn't matter
	D3DXMatrixIdentity(&mat);
	map->Init( mat );
	

	PartSys.RestoreDeviceObjects( "../data/flare.dds");
	PartSys2.RestoreDeviceObjects( "../data/fire.png");
	

	skinnedMesh = new SkinnedMesh("../data/tiny.x");
	D3DXCreateTextureFromFile(d3ddev, "../data/Tiny_skin.bmp", &mTex);
	for(int i = 0; i < nWarriors; i++)
	{
		warriors[i]->RestoreDeviceObjects();
	}
}

//-----------------------------------------------------------------------------
// Name: invalidateDeviceObjects()
// Desc: If the lost device can be restored, the application prepares the 
//       device by destroying all video-memory resources and any 
//       swap chains. This is typically accomplished by using the SAFE_RELEASE 
//       macro.
//-----------------------------------------------------------------------------
void GEngine::InvalidateDeviceObjects()
{

	Shaders::invalidateDeviceObjects();
	Effects::invalidateDeviceObjects();


	if( myFont != NULL )
	{
		int nNewRefCount = myFont->Release();

		if( nNewRefCount > 0 )
		{
			static char strError[255];
			sprintf_s( strError, "The Font object failed to cleanup properly.\n"
				"Release() returned a reference count of %d", nNewRefCount );
			MessageBox( NULL, strError, "ERROR", MB_OK | MB_ICONEXCLAMATION );
		}

		myFont = NULL;
	}
	if( mTex != NULL )
	{
		int nNewRefCount = mTex->Release();

		if( nNewRefCount > 0 )
		{
			static char strError[255];
			sprintf_s( strError, "The Tex object failed to cleanup properly.\n"
				"Release() returned a reference count of %d", nNewRefCount );
			MessageBox( NULL, strError, "ERROR", MB_OK | MB_ICONEXCLAMATION );
		}

		mTex = NULL;
	}


	map->invalidateDeviceObjects();
	PartSys.InvalidateDeviceObjects();
	PartSys2.InvalidateDeviceObjects();

	InvalidateModels();
}

//-----------------------------------------------------------------------------
// Name: shutDown()
// Desc: 
//-----------------------------------------------------------------------------
GEngine::~GEngine()
{

	InvalidateDeviceObjects();
	DeleteModels();

	SAFE_DELETE(projection);
	SAFE_DELETE(camera);
	SAFE_DELETE(FPSc);
	SAFE_DELETE(map);
	
    if( d3ddev != NULL )
    {
        int nNewRefCount = d3ddev->Release();

        if( nNewRefCount > 0 )
        {
            static char strError[255];
            sprintf_s( strError, "The device object failed to cleanup properly. \n"
                "Release() returned a reference count of %d", nNewRefCount );
            MessageBox( NULL, strError, "ERROR", MB_OK | MB_ICONEXCLAMATION );
        }

        d3ddev = NULL;
    }

    SAFE_RELEASE( md3dObject )
	DeleteGameObjects();
}

//-----------------------------------------------------------------------------
// Name: render()
// Desc: 
//-----------------------------------------------------------------------------
void GEngine::Render()
{
    //
    // Render 
    //
	lastTime    = currentTime;
	currentTime = timeGetTime();
	deltaTime   = currentTime - lastTime;

	float ElapsedTime = deltaTime/1000.0f;
	if (ElapsedTime < 0.001f) 
	{
		ElapsedTime = 0.001f; // To make sure it's positive
	}
	skinnedMesh->update(ElapsedTime);
	FPSc->UpdateFPS();
	D3DXMATRIX matView, matProj, matVP;
	matProj = projection->GetMat();
	matView = camera->GetMat();
	//printMatrix(matView);
	//printMatrix(matProj);
	D3DXMatrixMultiply(&matVP,&matView,&matProj);
	//printMatrix(matVP);



	d3ddev->Clear( 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER,
                         D3DCOLOR_COLORVALUE(0.15f,0.7f,0.1f,1.0f), 1.0f, 0 );

	

    d3ddev->BeginScene();
    {
		char qq[200];
		
		ID3DXLine *liniaMea;
		D3DXVECTOR2 puncte[2];
		puncte[0]=D3DXVECTOR2( (float) ptCurrentMousePosit.x, (float) ptCurrentMousePosit.y);
		puncte[1]=D3DXVECTOR2( (float) ptCurrentMousePosit.x + 3, (float) ptCurrentMousePosit.y + 3);

		D3DXCreateLine(d3ddev, &liniaMea);
		liniaMea->SetWidth(4.1f);
		liniaMea->Draw(puncte,2,D3DXCOLOR(255,255,0,255));
		liniaMea->Release();

		D3DXMATRIX MeshWorld;  
		ScaleAndTranslateAndRotate( MeshWorld, matVP,
									20.0f, 0.0f, 40.0f,  
									D3DXToRadian(SpinY), D3DXToRadian(SpinX), 0.0f,
									0.04f, 0.04f, 0.04f);
		




		


		d3ddev->SetVertexDeclaration(Shaders::getVertexDeclaration(0));


		d3ddev->SetVertexShader(Shaders::getVertexShader(0));
		d3ddev->SetPixelShader(Shaders::getPixelShader(0));
		map->Render( matVP );
		


		ID3DXEffect* FX1 = Effects::getEffect(0);
		
		FX1->SetMatrixArray(Effects::GetFinalXForms(), skinnedMesh->getFinalXFormArray(), skinnedMesh->numBones());
		FX1->SetValue(Effects::GetLight(), &mLight, sizeof(DirLight));
		FX1->SetMatrix(Effects::GetWVP(), &(MeshWorld*camera->GetMat()*projection->GetMat()));
		D3DXMATRIX worldInvTrans;
		D3DXMatrixInverse(&worldInvTrans, 0, &MeshWorld);
		D3DXMatrixTranspose(&worldInvTrans, &worldInvTrans);
		FX1->SetMatrix(Effects::GetWorldInvTrans(), &worldInvTrans);
		FX1->SetMatrix(Effects::GetWorld(), &MeshWorld);
		FX1->SetValue(Effects::GetMtrl0(), &mWhiteMtrl, sizeof(Mtrl));
		FX1->SetTexture(Effects::GetTex(), mTex);


		FX1->SetTechnique(Effects::GetTech());
		UINT numPasses = 0;
		FX1->Begin(&numPasses, 0);
		FX1->BeginPass(0);

		skinnedMesh->draw();

		FX1->EndPass();
		FX1->End();

		

 		//d3ddev->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
 		//d3ddev->SetRenderState(D3DRS_FILLMODE, D3DFILL_WIREFRAME);

		
		d3ddev->SetPixelShader(Shaders::getPixelShader(0));
		BOOL hitThisFrame =false;
		for( int i = 0; i < nWarriors; ++i )
		{
			warriors[i]->m_vPos.y = map->GetHeight( warriors[i]->m_vPos.x, warriors[i]->m_vPos.z )- warriors[i]->GetModel()->minB.y * warriors[i]->m_vScale.y;
			ScaleAndTranslateAndRotate( MeshWorld, matVP, warriors[i] );

			BOOL hit=false;
			if(MouseDown)
			{
				
				//camera->RotX(-0.001f);
				//camera->RotY(-0.01f);
				//camera->RotZ(-0.01f);

				D3DXVECTOR4 vRayOrigin;
				D3DXVECTOR3 vRayDirect;
				D3DXVECTOR3 vRayOrig, vRayDir;
				GetRay( ptCurrentMousePosit.x, ptCurrentMousePosit.y, vRayOrig, vRayDir, camera->GetMat(), projection->GetMat() );

				D3DXMATRIX mm;
				D3DXMatrixInverse(&mm ,NULL, &MeshWorld);
				D3DXVec3Transform(&vRayOrigin, &vRayOrig, &mm);
				D3DXVec3TransformNormal(&vRayDirect, &vRayDir, &mm);
				D3DXVec3Normalize(&vRayDirect, &vRayDirect);

				vRayOrig.x=vRayOrigin.x;
				vRayOrig.y=vRayOrigin.y;		
				vRayOrig.z=vRayOrigin.z;

				vRayDir.x=vRayDirect.x;
				vRayDir.y=vRayDirect.y;
				vRayDir.z=vRayDirect.z;


				FLOAT dist; 
				D3DXIntersect( warriors[i]->GetModel()->getMesh(), &vRayOrig, &vRayDir, &hit, NULL, NULL, NULL, &dist, NULL, NULL);

			}
			
			if ( hit )
			{
				hitThisFrame = true;
				selectedWarrior = true;
				SelectedWarriorIndex = i;
				warriors[SelectedWarriorIndex]->HP--;
			}
			if( selectedWarrior && i == SelectedWarriorIndex )
			{
				d3ddev->SetPixelShader(Shaders::getPixelShader(3));
			}	
			warriors[i]->Update(deltaTime);
			warriors[i]->Render();
			
			if( selectedWarrior && i == SelectedWarriorIndex )
			{
				d3ddev->SetPixelShader(Shaders::getPixelShader(0));
			}
	
		}


				bool hitMap = false;
		if(MouseDown)
		{
			D3DXVECTOR3 hitPoint;
			hitMap = map->checkCollision(ptCurrentMousePosit.x, ptCurrentMousePosit.y, camera->GetMat(), projection->GetMat(), hitPoint);
			
			if(selectedWarrior && !hitThisFrame)
			{
				
				
				warriors[SelectedWarriorIndex]->m_vTarget = hitPoint;
				warriors[SelectedWarriorIndex]->m_vDir = hitPoint - warriors[SelectedWarriorIndex]->m_vPos;
				warriors[SelectedWarriorIndex]->m_vDir.y = 0.0f;
				D3DXVec3Normalize(&warriors[SelectedWarriorIndex]->m_vDir,&warriors[SelectedWarriorIndex]->m_vDir);
				
				
				D3DXVECTOR3 noRotation = D3DXVECTOR3(0,0,-1);		
				float cosa = D3DXVec3Dot(&noRotation, &warriors[SelectedWarriorIndex]->m_vDir);
				if(warriors[SelectedWarriorIndex]->m_vDir.x > 0.0f)
				{
					warriors[SelectedWarriorIndex]->m_vRot.y = -acos(cosa);
				}
				else 
				{
					warriors[SelectedWarriorIndex]->m_vRot.y = acos(cosa);
				}
				
				//printVector(warriors[SelectedWarriorIndex]->m_vTarget);
				//warriors[SelectedWarriorIndex]->m_vPos.x = hitPoint.x ;
				//warriors[SelectedWarriorIndex]->m_vPos.z = hitPoint.z ;
			    //warriors[SelectedWarriorIndex]->m_vPos.y = map->GetHeight(hitPoint.x,hitPoint.z) ;

				
				
			}
			
		   	
		}



		d3ddev->SetPixelShader(Shaders::getPixelShader(0));
		d3ddev->SetVertexShader(Shaders::getVertexShader(0));
		for( int i = 0; i < nEntities; ++i )
		{
			ScaleAndTranslateAndRotate( MeshWorld, matVP, entities[i]);
			entities[i]->Render();
		}

		if(selectedWarrior)
		{
			//warriors[SelectedWarriorIndex]->m_vRot.y += 0.01f;
 			d3ddev->SetRenderState(D3DRS_ZENABLE, false);
			warriors[SelectedWarriorIndex]->RenderHP(matVP, camera);		
			warriors[SelectedWarriorIndex]->RenderStats();
 			d3ddev->SetRenderState(D3DRS_ZENABLE, true);
		}




		
		ParticleEmitter::SetRenderStates();

		d3ddev->SetVertexDeclaration(Shaders::getVertexDeclaration(1));
		d3ddev->SetVertexShader(Shaders::getVertexShader(2));
		d3ddev->SetPixelShader(Shaders::getPixelShader(1));

		PartSys.Update(ElapsedTime);
		PartSys.Render(camera->GetMat(), matVP);
		
		
		PartSys2.SetPos(warriors[3]->m_vPos);
		PartSys2.Update(ElapsedTime);
		PartSys2.Render(camera->GetMat(), matVP);



		ParticleEmitter::ResetRenderStates();



// 		d3ddev->SetVertexDeclaration(Shaders::getVertexDeclaration(0));
// 		d3ddev->SetVertexShader(Shaders::getVertexShader(0));
// 		d3ddev->SetPixelShader(Shaders::getPixelShader(0));

		sprintf_s(qq, " FPS : %f   Average: %f", FPSc->getFPS(), FPSc->getAvgFPS());
		DisplaySomeText(qq, 20, 10);
	}
    d3ddev->EndScene();


	
    //
    // If Present fails with D3DERR_DEVICELOST the application needs to be 
    // notified so it cleanup resources and reset the device.
    //

    d3ddev->Present( NULL, NULL, NULL, NULL );
}


void GEngine::DisplaySomeText(char *c, int x, int y)
{

      // Create a color for the text - in this case blue
      D3DCOLOR fontColor = D3DCOLOR_ARGB(255,0,0,255);   

      // Create a rectangle to indicate where on the screen it should be drawn
      RECT rct;
      rct.left=x;
      rct.right=730;
      rct.top=y;
      rct.bottom=rct.top+20;
       
      // Draw some text
      myFont->DrawText(NULL, c, -1, &rct, 0, fontColor );
}

void GEngine::LoadEntities(char* file)
{
	//TODO:Delete ex-models
	std::ifstream in;
	in.open(file);
	
	in>>nModels;
	char modelfile[200];
	for(int i = 0; i < nModels; i++)
	{
		in>>modelfile;
		

		models[i] = new Model(modelfile);
		strcat(modelfile,"bb");
		struct stat stFileInfo; 
		int intStat; 
	

		D3DXVECTOR3 minBounds,maxBounds;
		
		// Attempt to get the file attributes 
		intStat = stat(modelfile,&stFileInfo); 
		if(intStat == 0)
		{
			std::ifstream in2;
			in2.open(modelfile);
			in2>>minBounds.x>>minBounds.y>>minBounds.z>>maxBounds.x>>maxBounds.y>>maxBounds.z;
			in2.close();
		}	
		else
		{

			BYTE* pVertices=NULL;
			HRESULT hr;
			hr=models[i]->getMesh()->LockVertexBuffer(D3DLOCK_READONLY, (LPVOID*)&pVertices);
			if (FAILED(hr))
			{			
				MessageBox(0, "Failed to lock model vertex !", 0, 0);
				return;
			}

			D3DXComputeBoundingBox((D3DXVECTOR3*)pVertices, models[i]->getMesh()->GetNumVertices(), D3DXGetFVFVertexSize(models[i]->getMesh()->GetFVF()), &minBounds, &maxBounds);
			models[i]->getMesh()->UnlockVertexBuffer();
			
			std::ofstream outbb;
			outbb.open(modelfile);
			outbb<<minBounds.x<<" "<<minBounds.y<<" "<<minBounds.z<<"\n"<<maxBounds.x<<" "<<maxBounds.y<<" "<<maxBounds.z;
			outbb.close();
		}
		models[i]->SetMinBounds(minBounds);
		models[i]->SetMaxBounds(maxBounds);
	}
	int j;
	in>>nEntities;
	for(int i = 0; i < nEntities; i++)
	{
		in>>j;
		entities[i] = new Entity( models[j] );
		in>>entities[i]->m_vPos.x>>entities[i]->m_vPos.y>>entities[i]->m_vPos.z;
		in>>entities[i]->m_vRot.x>>entities[i]->m_vRot.y>>entities[i]->m_vRot.z;
		in>>entities[i]->m_vScale.x>>entities[i]->m_vScale.y>>entities[i]->m_vScale.z;
	}
	in>>nDestructibles;
	for(int i = 0; i < nDestructibles; i++)
	{
		in>>j;
		destructibles[i] = new Destructible( models[j] );
		in>>destructibles[i]->m_vPos.x>>destructibles[i]->m_vPos.y>>destructibles[i]->m_vPos.z;
		in>>destructibles[i]->m_vRot.x>>destructibles[i]->m_vRot.y>>destructibles[i]->m_vRot.z;
		in>>destructibles[i]->m_vScale.x>>destructibles[i]->m_vScale.y>>destructibles[i]->m_vScale.z;
	}
	in>>nWarriors;
	for(int i = 0; i < nWarriors; i++)
	{
		in>>j;
		warriors[i] = new Warrior( models[j] );
		in>>warriors[i]->m_vPos.x>>warriors[i]->m_vPos.y>>warriors[i]->m_vPos.z;
		in>>warriors[i]->m_vRot.x>>warriors[i]->m_vRot.y>>warriors[i]->m_vRot.z;
		in>>warriors[i]->m_vScale.x>>warriors[i]->m_vScale.y>>warriors[i]->m_vScale.z;
		in>>warriors[i]->HP>>warriors[i]->maxHP>>warriors[i]->damage>>warriors[i]->armor;
	}
	in.close();
}
void GEngine::InvalidateModels()
{
	for(int i = 0; i < nModels; i++)
	{
		models[i]->invalidateDeviceObjects();
	}
	for(int i = 0; i < nWarriors; i++)
	{
		warriors[i]->InvalidateDeviceObjects();
	}
}
void GEngine::DeleteModels()
{
	for(int i = 0; i < nModels; i++)
	{
		models[i]->DeleteModel();
	}
	delete skinnedMesh;
}
void GEngine::DeleteGameObjects()
{
	for(int i = 0; i < nEntities; i++)
	{
		entities[i]->~Entity();
	}

	for(int i = 0; i < nDestructibles; i++)
	{
		destructibles[i]->~Destructible();
	}

	for(int i = 0; i < nWarriors; i++)
	{
		warriors[i]->~Warrior();
	}
}
